package com.kdl.webconfig.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class DateUtils {
    public static final Long LONG_MS_SECOND = 1000L;
    public static final Long LONG_MS_MINUTES;
    public static final Long LONG_MS_HOUR;
    public static final Long LONG_MS_DAY;
    public static final String FORMAT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_DATE_PATTERN = "yyyy-MM-dd";
    public static final String FORMAT_DATE_MMDD_WITH_HYPHEN = "MM-dd";
    public static final String FORMAT_DATE_YYYYMMDD = "yyyyMMdd";
    public static final String FORMAT_DATE_YYYYMMDD_WITH_SLASH = "yyyy/MM/dd";
    public static final String FORMAT_DATETIME_WITH_SLASH = "yyyy/MM/dd HH:mm:ss";
    public static final String FORMAT_DATETIME_WITH_SLASH_ = "yyyy/MM/dd HH:mm:ss";
    public static final String FORMAT_DATETIME_HHMM = "yyyy-MM-dd HH:mm";
    public static final String FORMAT_DATETIME_CHAR = "yyyy年MM月dd日";
    public static final String FORMAT_MONTH_PATTERN = "yyyy-MM";
    private static Log logger;

    public DateUtils() {
    }

    public static LocalDateTime parseStrToLocalDateTime(String dateTimeStr, String patternStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(patternStr);
        LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr, formatter);
        return localDateTime;
    }

    public static String formatLocalDateTimeToStr(LocalDateTime localDT, String patternStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(patternStr);
        String localDateTimeStr = formatter.format(localDT);
        return localDateTimeStr;
    }

    public static Long calculateTwoLocalDateIntervalDays(LocalDate localDate01, LocalDate localDate02) {
        return Period.between(localDate01, localDate02).get(ChronoUnit.DAYS);
    }

    public static Date now() {
        return now(false);
    }

    public static Date now(boolean filterTime) {
        long sysTimeMillis = System.currentTimeMillis();
        return filterTime ? new Date(sysTimeMillis - (sysTimeMillis + (long)TimeZone.getDefault().getRawOffset()) % 86400000L) : new Date(sysTimeMillis);
    }

    public static Date toDate(long timestamp) {
        return new Date(timestamp);
    }

    public static Date toDate(String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        } else {
            String format;
            if (dateStr.matches("^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$")) {
                format = "yyyy-MM-dd";
            } else {
                if (!dateStr.matches("^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\\s+(20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d$")) {
                    return null;
                }

                format = "yyyy-MM-dd HH:mm:ss";
            }

            return toDate(dateStr, format);
        }
    }

    public static Date toDate(String dateStr, String format) {
        try {
            Date parse = (new SimpleDateFormat(format)).parse(dateStr);
            return parse;
        } catch (ParseException var4) {
            return null;
        }
    }

    public static String toSimpleStr(Date date, boolean filterTime) {
        if (date == null) {
            return null;
        } else {
            String format;
            if (filterTime) {
                format = "yyyy-MM-dd";
            } else {
                format = "yyyy-MM-dd HH:mm:ss";
            }

            return toStr(date, format);
        }
    }

    public static String toSimpleStr(Long timeMillis) {
        return toSimpleStr(timeMillis, false);
    }

    public static String toSimpleStr(Long timeMillis, boolean filterTime) {
        return timeMillis != null && timeMillis > 0L ? toSimpleStr(new Date(timeMillis), filterTime) : "";
    }

    public static String toSimpleStr(Date date) {
        return toSimpleStr(date, false);
    }

    public static String toStr(Date date, String format) {
        if (date != null && !StringUtils.isBlank(format)) {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            return formatter.format(date);
        } else {
            return "";
        }
    }

    public static String withTime(String date) {
        return withTime(date, 0L);
    }

    public static String withTime(String date, long secondsPastNow) {
        if (StringUtils.isBlank(date)) {
            return date;
        } else {
            String regex = "^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$";
            if (!date.matches(regex)) {
                return date;
            } else {
                long timeMillis = System.currentTimeMillis() + secondsPastNow * 1000L;
                Date timeDate = new Date(timeMillis);
                String time = toStr(timeDate, "HH:mm:ss");
                return String.join(" ", date, time);
            }
        }
    }

    public static Date datePastSeconds(Date date, long pastSeconds) {
        if (date == null) {
            return null;
        } else {
            long time = date.getTime();
            time += pastSeconds * 1000L;
            return new Date(time);
        }
    }

    public static Date datePastMunites(Date date, long pastMunites) {
        if (date == null) {
            return null;
        } else {
            long time = date.getTime();
            time += pastMunites * 1000L * 60L;
            return new Date(time);
        }
    }

    public static Date datePastDays(Date date, int pastDays) {
        return datePastSeconds(date, (long)(pastDays * 24 * 60 * 60 - 1));
    }

    public static Date filterTime(Date date) {
        if (date == null) {
            return null;
        } else {
            String dateStr = toSimpleStr(date, true);
            return toDate(dateStr);
        }
    }

    public static final String getCurrentDateStr(String format) {
        return format(getCurrentDate(), format);
    }

    public static final Date getCurrentTime() {
        return Calendar.getInstance().getTime();
    }

    public static final Date getCurrentDate() {
        return getDateIgnoreTime(Calendar.getInstance().getTime());
    }

    public static final Date[] getDifferenceDate(Date baseDate) {
        Date[] date = new Date[2];
        Calendar cal = Calendar.getInstance();
        cal.setTime(baseDate);
        cal.set(11, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(14, 0);
        date[0] = cal.getTime();
        cal.add(5, 1);
        date[1] = cal.getTime();
        return date;
    }

    public static final Date getDateIgnoreTime(Date baseDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(baseDate);
        cal.set(11, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        cal.set(14, 0);
        return cal.getTime();
    }

    public static final int compareByDate(Date date1, Date date2) {
        int num = getDaysBetweenDates(date1, date2);
        if (num > 0) {
            return 1;
        } else {
            return num < 0 ? -1 : num;
        }
    }

    public static final int compareByDateTime(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            TimeZone timeZone = TimeZone.getDefault();
            long beginOffset = (long)timeZone.getRawOffset();
            long endOffset = beginOffset;
            if (timeZone.inDaylightTime(date1)) {
                beginOffset += (long)timeZone.getDSTSavings();
            }

            if (timeZone.inDaylightTime(date2)) {
                endOffset = beginOffset + (long)timeZone.getDSTSavings();
            }

            long milli1 = (date1.getTime() + beginOffset) / 1000L;
            long milli2 = (date2.getTime() + endOffset) / 1000L;
            int retVal = 0;
            if (milli1 > milli2) {
                retVal = 1;
            } else if (milli1 < milli2) {
                retVal = -1;
            }

            return retVal;
        } else {
            throw new IllegalArgumentException("Date cannot be null.");
        }
    }

    public static final int compareByTimestamp(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            TimeZone timeZone = TimeZone.getDefault();
            long beginOffset = (long)timeZone.getRawOffset();
            long endOffset = beginOffset;
            if (timeZone.inDaylightTime(date1)) {
                beginOffset += (long)timeZone.getDSTSavings();
            }

            if (timeZone.inDaylightTime(date2)) {
                endOffset = beginOffset + (long)timeZone.getDSTSavings();
            }

            long milli1 = date1.getTime() + beginOffset;
            long milli2 = date2.getTime() + endOffset;
            int retVal = 0;
            if (milli1 > milli2) {
                retVal = 1;
            } else if (milli1 < milli2) {
                retVal = -1;
            }

            return retVal;
        } else {
            throw new IllegalArgumentException("Date cannot be null.");
        }
    }

    public static final int getDaysBetweenDates(Date endDate, Date beginDate) {
        if (endDate != null && beginDate != null) {
            return getDaysBetweenDates((TimeZone)null, endDate, beginDate);
        } else {
            throw new IllegalArgumentException("Date cannot be null.");
        }
    }

    public static final Long getSecendsBetweenDates(Date endDate, Date beginDate) {
        return getNumberBetweenDates((TimeZone)null, endDate, beginDate, LONG_MS_SECOND);
    }

    public static final Long getMinutesBetweenDates(Date endDate, Date beginDate) {
        return getNumberBetweenDates((TimeZone)null, endDate, beginDate, LONG_MS_MINUTES);
    }

    public static final Long getHoursBetweenDates(Date endDate, Date beginDate) {
        return getNumberBetweenDates((TimeZone)null, endDate, beginDate, LONG_MS_HOUR);
    }

    public static final int getDaysBetweenDates(TimeZone timeZone, Date endDate, Date beginDate) {
        return getNumberBetweenDates(timeZone, endDate, beginDate, LONG_MS_DAY).intValue();
    }

    public static final Long getNumberBetweenDates(TimeZone timeZone, Date endDate, Date beginDate, Long unitMS) {
        if (beginDate != null && endDate != null) {
            if (timeZone == null) {
                timeZone = TimeZone.getDefault();
            }

            long beginOffset = (long)timeZone.getRawOffset();
            long endOffset = beginOffset;
            if (timeZone.inDaylightTime(beginDate)) {
                beginOffset += (long)timeZone.getDSTSavings();
            }

            if (timeZone.inDaylightTime(endDate)) {
                endOffset = beginOffset + (long)timeZone.getDSTSavings();
            }

            long endDays = (endDate.getTime() + endOffset) / unitMS;
            long beginDays = (beginDate.getTime() + beginOffset) / unitMS;
            return endDays - beginDays;
        } else {
            throw new IllegalArgumentException("Date cannot be null.");
        }
    }

    public static final int getYear(Date date) {
        return date == null ? 0 : getCalendarField(date, 1);
    }

    public static final int getMonth(Date date) {
        return date == null ? 0 : getCalendarField(date, 2) + 1;
    }

    public static final int getDay(Date date) {
        return date == null ? 0 : getCalendarField(date, 5);
    }

    public static final int getHour(Date date) {
        return date == null ? 0 : getCalendarField(date, 11);
    }

    public static final int getMinute(Date date) {
        return date == null ? 0 : getCalendarField(date, 11);
    }

    public static final int getSecond(Date date) {
        return date == null ? 0 : getCalendarField(date, 13);
    }

    public static final int getMilliSecond(Date date) {
        return date == null ? 0 : getCalendarField(date, 14);
    }

    public static final int getCalendarField(Date date, int field) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(field);
    }

    public static final Date addYear(Date date, int value) {
        return add(date, 1, value);
    }

    public static final Date addMonth(Date date, int value) {
        return add(date, 2, value);
    }

    public static final Date addDay(Date date, int value) {
        return add(date, 5, value);
    }

    public static final Date addHour(Date date, int value) {
        return add(date, 11, value);
    }

    public static final Date addMinute(Date date, int value) {
        return add(date, 12, value);
    }

    public static final Date addSecond(Date date, int value) {
        return add(date, 13, value);
    }

    public static final Date addMilliSecond(Date date, int value) {
        return add(date, 14, value);
    }

    public static final Date add(Date date, int field, int value) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(field, value);
        return cal.getTime();
    }

    public static final Date setYear(Date date, int value) {
        return set(date, 1, value);
    }

    public static final Date setMonth(Date date, int value) {
        return set(date, 2, value);
    }

    public static final Date setDay(Date date, int value) {
        return set(date, 5, value);
    }

    public static final Date setHour(Date date, int value) {
        return set(date, 11, value);
    }

    public static final Date setMinute(Date date, int value) {
        return set(date, 12, value);
    }

    public static final Date setSecond(Date date, int value) {
        return set(date, 13, value);
    }

    public static final Date setMilliSecond(Date date, int value) {
        return set(date, 14, value);
    }

    public static final Date set(Date date, int field, int value) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(field, value);
        return cal.getTime();
    }

    public static final Date lastDate(Date date) {
        return addDay(addMonth(setDay(date, 1), 1), -1);
    }

    public static final Date firstDate(Date date) {
        return setDay(date, 1);
    }

    public static final boolean isLastDate(Date date) {
        Date lastDate = lastDate(date);
        return compareByDate(date, lastDate) == 0;
    }

    public static final boolean isFirstDate(Date date) {
        Date firstDate = firstDate(date);
        return compareByDate(date, firstDate) == 0;
    }

    public static final boolean isSameDate(Date date1, Date date2) {
        return compareByDate(getDateIgnoreTime(date1), getDateIgnoreTime(date2)) == 0;
    }

    public static boolean isSameMonth(Date date1, Date date2) {
        return getMonth(date1) == getMonth(date2);
    }

    public static boolean isSameYear(Date date1, Date date2) {
        return getYear(date1) == getYear(date2);
    }

    public static final String format(Date date, String fmtString) {
        DateFormat format = new SimpleDateFormat(fmtString);
        return format.format(date);
    }

    public static final String formatDate(Date date) {
        return null == date ? null : format(date, "yyyy-MM-dd");
    }

    public static final String formatTime(Date date) {
        return null == date ? null : format(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static final Date parse(String dateString, String fmtString) {
        Date date = null;

        try {
            DateFormat format = new SimpleDateFormat(fmtString);
            format.setLenient(false);
            date = format.parse(dateString);
        } catch (ParseException var4) {
            logger.error("parse(String, String) parse error", var4);
        }

        return date;
    }

    public static final Date parseDate(String dateString) {
        return parse(dateString, "yyyy-MM-dd");
    }

    public static final Date parseDateString(String dateString) {
        return parse(dateString, "yyyyMMdd");
    }

    public static final Date parseTime(String dateString) {
        return parse(dateString, "yyyy-MM-dd HH:mm:ss");
    }

    public static int getLastDay(int year, int month) {
        int day = 1;
        Calendar cal = Calendar.getInstance();
        cal.set(year, month - 1, day);
        int last = cal.getActualMaximum(5);
        return last;
    }

    public static int getWeek() {
        int week = 0;

        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setFirstDayOfWeek(2);
            week = calendar.get(8);
        } catch (Exception var2) {
            var2.printStackTrace();
        }

        return week;
    }

    public static int getWeek(Date date) {
        int week = 0;

        try {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.setFirstDayOfWeek(1);
            week = cal.get(8);
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return week;
    }

    public static int getDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day4Week = c.get(7) - 1;
        if (day4Week == 0) {
            day4Week = 7;
        }

        return day4Week;
    }

    public static String date2WeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int weekDay = calendar.get(7);
        String result;
        switch(weekDay) {
        case 1:
            result = "周日";
            break;
        case 2:
            result = "周一";
            break;
        case 3:
            result = "周二";
            break;
        case 4:
            result = "周三";
            break;
        case 5:
            result = "周四";
            break;
        case 6:
            result = "周五";
            break;
        case 7:
            result = "周六";
            break;
        default:
            result = "";
        }

        return result;
    }

    public static int dateOfWeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int weekDay = calendar.get(7);
        Integer result;
        switch(weekDay) {
        case 1:
            result = 7;
            break;
        case 2:
            result = 1;
            break;
        case 3:
            result = 2;
            break;
        case 4:
            result = 3;
            break;
        case 5:
            result = 4;
            break;
        case 6:
            result = 5;
            break;
        case 7:
            result = 6;
            break;
        default:
            result = null;
        }

        return result;
    }

    public static String parseLongToDateTime(long number) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date(number));
    }

    public static String parseLongToDate(long number) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date(number));
    }

    public static Date parseLongDate(long number) {
        new SimpleDateFormat("yyyy-MM-dd");
        return new Date(number);
    }

    public static String parseLongToInteger(long number) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(new Date(number));
    }

    public static String duration(Date start, Date end) {
        if (start != null && end != null) {
            long diff = end.getTime() - start.getTime();
            long MS_IN_A_DAY = 86400000L;
            long MS_IN_AN_HOUR = 3600000L;
            long MS_IN_A_MINUTE = 60000L;
            long numDays = diff / 86400000L;
            diff %= 86400000L;
            long numHours = diff / 3600000L;
            diff %= 3600000L;
            long numMinutes = diff / 60000L;
            StringBuilder sb = new StringBuilder();
            if (numDays > 0L) {
                sb.append(numDays).append("天");
            }

            if (numHours > 0L) {
                sb.append(numHours).append("时");
            }

            if (numMinutes > 0L) {
                sb.append(numMinutes).append("分");
            }

            return sb.toString();
        } else {
            return "";
        }
    }

    public static int getAgeByBirth(Date birthday, Date date) {
        boolean var2 = false;

        try {
            Calendar now = Calendar.getInstance();
            now.setTime(new Date());
            Calendar birth = Calendar.getInstance();
            birth.setTime(birthday);
            int age;
            if (birth.after(now)) {
                age = 0;
            } else {
                age = now.get(1) - birth.get(1);
                if (now.get(6) > birth.get(6)) {
                    ++age;
                }
            }

            return age;
        } catch (Exception var5) {
            return 0;
        }
    }

    public static Date plusSeconds(Date date, long pastSeconds) {
        if (date == null) {
            return null;
        } else {
            long time = date.getTime();
            time += pastSeconds * 1000L;
            return new Date(time);
        }
    }

    public static Date plusDays(Date date, int pastDays) {
        return plusSeconds(date, (long)(pastDays * 24 * 60 * 60));
    }

    public static Date subtractSeconds(Date date, long pastSeconds) {
        if (date == null) {
            return null;
        } else {
            long time = date.getTime();
            time -= pastSeconds * 1000L;
            return new Date(time);
        }
    }

    public static Date subtractDays(Date date, int pastDays) {
        return subtractSeconds(date, (long)(pastDays * 24 * 60 * 60));
    }

    public static int dayForMonthCount(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalDate localDate = localDateTime.toLocalDate();
        return localDate.withMonth(Month.MAY.getValue()).lengthOfMonth();
    }

    public static void main(String[] args) {
        Date date = new Date();
        int i = dayForMonthCount(date);
        System.out.println("当前月份有" + i + "天");
        System.out.println(date.getTime());
        Date newDate = setMilliSecond(date, 999);
        System.out.println(newDate.getTime());
        newDate = setMinute(date, 50);
        System.out.println(newDate);
        System.out.println(date2WeekDay(new Date()));
        int i1 = dateOfWeekDay(getCurrentTime());
        System.out.println(i1);
    }

    static {
        LONG_MS_MINUTES = 60L * LONG_MS_SECOND;
        LONG_MS_HOUR = 60L * LONG_MS_MINUTES;
        LONG_MS_DAY = 24L * LONG_MS_HOUR;
        logger = LogFactory.getLog(DateUtils.class);
    }
}
